summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorOliver Reiche <oliver.reiche@huawei.com>2022-12-22 18:21:16 +0100
committerOliver Reiche <oliver.reiche@huawei.com>2023-01-27 17:12:28 +0100
commit2d541fd31a50cc5a273fd3faa010f66ffe4abb15 (patch)
tree53f816c51667c6acdb6a70957726898a42e6b32d /doc
parent7a90f68e5207d541dea937aaff5b6c4c499b8968 (diff)
downloadrules-cc-2d541fd31a50cc5a273fd3faa010f66ffe4abb15.tar.gz
Add examples for interoperability with CMake
- consuming CMake libraries - being consumed by CMake
Diffstat (limited to 'doc')
-rw-r--r--doc/being-consumed-by-cmake.org165
-rw-r--r--doc/consume-cmake-libraries.org137
2 files changed, 302 insertions, 0 deletions
diff --git a/doc/being-consumed-by-cmake.org b/doc/being-consumed-by-cmake.org
new file mode 100644
index 0000000..86c1825
--- /dev/null
+++ b/doc/being-consumed-by-cmake.org
@@ -0,0 +1,165 @@
+* Being consumed by CMake
+
+To support libraries built with JustBuild to be consumed by CMake, the rule
+~["CC", "install-with-deps"]~ can be used. This rule will install the library's
+artifacts, its public headers, and a pkg-config file, which can be used by CMake
+to properly consume the library.
+
+In this example, we show how to build and install the ~ssl~ library with
+JustBuild, so it can be picked up and used by CMake afterwards.
+
+** Example: Build and install the ~ssl~ Library with JustBuild
+
+First make sure that ~just~, ~just-mr~, and ~just-import-git~ are available in
+your ~PATH~. Then, define a new workspace by creating the ~ROOT~ marker.
+
+#+BEGIN_SRC sh
+$ touch ROOT
+#+END_SRC
+
+The ~ssl~ library that we want to use is a defined dependency of the JustBuild
+repository ~just/ssl~. To define a repository for that library, create the
+following ~repos.template.json~ file.
+
+#+SRCNAME: repos.template.json
+#+BEGIN_SRC js
+{ "main": "ssl"
+, "repositories":
+ { "ssl":
+ { "repository": {"type": "file", "path": "."}
+ , "bindings": {"rules": "rules-cc", "just-ssl": "just/ssl"}
+ }
+ }
+}
+#+END_SRC
+
+and import the ~rules-cc~ and JustBuild repository, including its dependency
+~just/ssl~, via:
+
+#+BEGIN_SRC sh
+$ cat repos.template.json \
+ | just-import-git -C - --as just -b master https://github.com/just-buildsystem/justbuild \
+ | just-import-git -C - --as rules-cc -b master https://github.com/just-buildsystem/rules-cc \
+ > repos.json
+$
+#+END_SRC
+
+Next, the following ~TARGETS~ file needs to be provided.
+
+#+SRCNAME: TARGETS
+#+BEGIN_SRC js
+{ "ssl-lib":
+ { "type": ["@", "rules", "CC", "library"]
+ , "name": ["ssl"]
+ , "deps": [["@", "just-ssl", "", "ssl"]]
+ }
+, "ssl-pkg":
+ {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["ssl-lib"]}
+}
+#+END_SRC
+
+The library target ~ssl-lib~ specifies the name ~"ssl"~ (also used as package
+name) and a dependency on the ~ssl~ library from ~just-ssl~. Note that although
+this library target is merely a "wrapper" (header-only library without headers),
+it could equally well be a full-blown library target. Furthermore, the package
+target ~ssl-pkg~ installs the ~ssl-lib~ target including its dependencies and
+generates a pkg-config file that can be later used by CMake.
+
+Finally, the ~ssl-pkg~ target can be built and installed to a specific ~PREFIX~
+(note that ~OS~ and ~ARCH~ must be set as well).
+
+#+BEGIN_SRC sh
+$ export PREFIX=/tmp/just_ssl
+$ just-mr install -D'{"OS":"linux", "ARCH":"x64_64", "PREFIX":"'$PREFIX'"}' -o $PREFIX ssl-pkg
+INFO: Requested target is [["@","ssl","","ssl-pkg"],{"ARCH":"x64_64","OS":"linux","PREFIX":"/tmp/just_ssl"}]
+INFO: Analysed target [["@","ssl","","ssl-pkg"],{"ARCH":"x64_64","OS":"linux","PREFIX":"/tmp/just_ssl"}]
+INFO: Export targets found: 0 cached, 2 uncached, 0 not eligible for caching
+INFO: Discovered 269 actions, 3 trees, 1 blobs
+INFO: Building [["@","ssl","","ssl-pkg"],{"ARCH":"x64_64","OS":"linux","PREFIX":"/tmp/just_ssl"}].
+PROG: [ 79%] 0 cached, 215 run, 8 processing (["@","just/ssl","","crypto-lib"]#105, ...).
+INFO: Processed 269 actions, 0 cache hits.
+INFO: Artifacts can be found in:
+ /tmp/just_ssl/include/openssl/aead.h [6d78db27d24746b39eacc20374697476e080c9f6:21054:f]
+ ...
+ /tmp/just_ssl/lib/libcrypto.a [df64da43f0168a717d09d609bf0c631d29c86b61:2336092:f]
+ /tmp/just_ssl/lib/libssl.a [77d2c2bfbe3ef3608895c854f1d1f6e1c200efd0:852620:f]
+ /tmp/just_ssl/share/pkgconfig/ssl.pc [9b69c758430f5b5fb6ff7a9b1f1ffc89471509af:406:f]
+$
+#+END_SRC
+
+** Example: Consume the installed ~ssl~ Library with CMake
+
+As an example, a minimal ~main.c~ file is created that depends on the ~ssl~
+library.
+
+#+SRCNAME: main.c
+#+BEGIN_SRC C
+#include <openssl/evp.h>
+
+int main(int argc, char** argv) {
+ OpenSSL_add_all_algorithms();
+ return 0;
+}
+#+END_SRC
+
+In the ~CMakeLists.txt~ file, the ~pkg_check_modules()~ macro can be used to
+determine the compile and linker flags needed to consume our ~ssl~ library with
+CMake.
+
+#+SRCNAME: CMakeLists.txt
+#+BEGIN_SRC cmake
+cmake_minimum_required(VERSION 3.1)
+
+project(test_ssl)
+
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(SSL REQUIRED ssl)
+
+add_executable(main main.c)
+target_include_directories(main PRIVATE ${SSL_INCLUDE_DIRS})
+target_compile_options(main PRIVATE ${SSL_CFLAGS_OTHER})
+target_link_directories(main PRIVATE ${SSL_LIBRARY_DIRS})
+target_link_libraries(main PRIVATE ${SSL_LDFLAGS_OTHER} ${SSL_LIBRARIES})
+#+END_SRC
+
+Note that ~${SSL_LDFLAGS_OTHER}~ can be omitted if the ~ssl-pkg~ target was
+defined with a non-empty value for the field ~"flat-libs"~ (see rule
+documentation of ~["CC", "install-with-deps"]~).
+
+Finally, when running CMake, make sure to set the ~CMAKE_PREFIX_PATH~ to the
+previously used install prefix in order to successfully find the installed ~ssl~
+library and its pkg-config file.
+
+#+BEGIN_SRC sh
+$ cmake -DCMAKE_PREFIX_PATH=/tmp/just_ssl -S . -B /tmp/test_ssl
+-- The C compiler identification is GNU 10.2.1
+-- The CXX compiler identification is GNU 10.2.1
+-- Detecting C compiler ABI info
+-- Detecting C compiler ABI info - done
+-- Check for working C compiler: /usr/bin/cc - skipped
+-- Detecting C compile features
+-- Detecting C compile features - done
+-- Detecting CXX compiler ABI info
+-- Detecting CXX compiler ABI info - done
+-- Check for working CXX compiler: /usr/bin/c++ - skipped
+-- Detecting CXX compile features
+-- Detecting CXX compile features - done
+-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2")
+-- Checking for module 'ssl'
+-- Found ssl, version unknown
+-- Configuring done
+-- Generating done
+-- Build files have been written to: /tmp/test_ssl
+$ cmake --build /tmp/test_ssl
+[ 50%] Building CXX object CMakeFiles/main.dir/main.c.o
+[100%] Linking CXX executable main
+[100%] Built target main
+$
+#+END_SRC
+
+Note that if the package is moved to a different location, the ~prefix~ variable
+within the pkg-config file ~share/pkgconfig/ssl.pc~ must be updated as well.
+Alternatively, CMake can be instructed to automatically guess the correct prefix
+by setting the variable ~PKG_CONFIG_ARGN~ to ~"--define-prefix"~ (either on the
+command line or in the ~CMakeLists.txt~). However, this is a fairly recent CMake
+feature and requires at least CMake version 3.22.
diff --git a/doc/consume-cmake-libraries.org b/doc/consume-cmake-libraries.org
new file mode 100644
index 0000000..4aa75b6
--- /dev/null
+++ b/doc/consume-cmake-libraries.org
@@ -0,0 +1,137 @@
+* Consume CMake Libraries
+
+To support libraries built with CMake to be consumed by JustBuild, the rule
+~["CC/foreign/cmake", "library"]~ can be used. This rule will run CMake and
+collect the library's artifacts, public headers, and pkg-config files (if
+available), to produce a proper JustBuild library target.
+
+In this example, we show how to consume the ~gtest~ library built with CMake
+using JustBuild.
+
+** Example: Build the ~gtest~ Library with CMake
+
+First make sure that ~just~, ~just-mr~, and ~just-import-git~ are available in
+your ~PATH~. Then, define a new workspace by creating a ~ROOT~ marker.
+
+#+BEGIN_SRC sh
+$ touch ROOT
+#+END_SRC
+
+To define a repository for the
+[[https://github.com/google/googletest/tree/v1.13.0][gtest]] library, create the
+following ~repos.template.json~ file.
+
+#+SRCNAME: repos.template.json
+#+BEGIN_SRC js
+{ "main": "tests"
+, "repositories":
+ { "imports": {"repository": {"type": "file", "path": "imports"}}
+ , "gtest":
+ { "repository":
+ { "type": "git"
+ , "branch": "v1.13.0"
+ , "commit": "b796f7d44681514f58a683a3a71ff17c94edb0c1"
+ , "repository": "https://github.com/google/googletest"
+ }
+ , "target_root": "imports"
+ , "target_file_name": "gtest.TARGETS"
+ , "bindings": {"rules": "rules-cc"}
+ }
+ , "tests":
+ { "repository": {"type": "file", "path": "."}
+ , "bindings": {"rules": "rules-cc", "gtest": "gtest"}
+ }
+ }
+}
+#+END_SRC
+
+Now the missing ~rules-cc~ repository can be imported via:
+
+#+BEGIN_SRC sh
+$ just-import-git -C repos.template.json --as rules-cc -b master https://github.com/just-buildsystem/rules-cc > repos.json
+$
+#+END_SRC
+
+Create the file ~imports/gtest.TARGETS~ with the following content.
+
+#+SRCNAME: imports/gtest.TARGETS
+#+BEGIN_SRC js
+{ "gtest_main":
+ { "type": ["@", "rules", "CC/foreign/cmake", "library"]
+ , "name": ["gtest_main"]
+ , "version": ["1", "13", "0"]
+ , "project": [["TREE", null, "."]]
+ , "defines": ["BUILD_SHARED_LIBS=ON"]
+ , "out_hdr_dirs": ["gtest"]
+ , "out_libs": ["libgtest_main.so.1.13.0", "libgtest.so.1.13.0"]
+ , "pkg-config": ["gtest_main.pc", "gtest.pc"]
+ }
+}
+#+END_SRC
+
+The library ~gtest_main~ uses the rule ~["CC/foreign/cmake", "library"]~. It
+sets ~defines~ to build shared libraries and collects the public header
+directory ~gtest~, as well as the two libraries ~libgtest_main.so.1.13.0~ and
+~libgtest.so.1.13.0~ (in this particular link order). Furthermore, to
+automatically infer public compile and link flags (e.g., a link dependency to
+the system's ~pthread~ library), the pkg-config files ~gtest_main.pc~ and
+~gtest.pc~ are read, with the former (entry point) depending on the latter.
+
+Now, create the actual ~test~ target, which consumes the ~gtest_main~ library,
+by creating the following ~TARGETS~ file.
+
+#+SRCNAME: TARGETS
+#+BEGIN_SRC js
+{ "test":
+ { "type": ["@", "rules", "CC/test", "test"]
+ , "name": ["test"]
+ , "srcs": ["test.cpp"]
+ , "private-deps": [["@", "gtest", "", "gtest_main"]]
+ }
+}
+#+END_SRC
+
+The last file missing yet is the actual test source file ~test.cpp~.
+
+#+SRCNAME: test.cpp
+#+BEGIN_SRC cpp
+#include <gtest/gtest.h>
+
+TEST(CastTest, double) {
+ EXPECT_EQ (42.0, double(42));
+}
+#+END_SRC
+
+Finally, build the ~test~ target to run the test.
+
+#+BEGIN_SRC sh
+$ just-mr build test -Pstdout
+INFO: Requested target is [["@","tests","","test"],{}]
+INFO: Analysed target [["@","tests","","test"],{}]
+INFO: Export targets found: 0 cached, 0 uncached, 0 not eligible for caching
+INFO: Target tainted ["test"].
+INFO: Discovered 7 actions, 2 trees, 3 blobs
+INFO: Building [["@","tests","","test"],{}].
+INFO: Processed 7 actions, 0 cache hits.
+INFO: Artifacts built, logical paths are:
+ result [7ef22e9a431ad0272713b71fdc8794016c8ef12f:5:f]
+ stderr [8b137891791fe96927ad78e64b0aad7bded08bdc:1:f]
+ stdout [fc46e9e95a8a393e3c94875d66b0de956305f6a6:728:f]
+ time-start [93887fee067665917f67e2cb757dd30bf22b23a0:11:f]
+ time-stop [93887fee067665917f67e2cb757dd30bf22b23a0:11:f]
+ (1 runfiles omitted.)
+Running main() from src/gtest_main.cc
+[==========] Running 1 test from 1 test suite.
+[----------] Global test environment set-up.
+[----------] 1 test from CastTest
+[ RUN ] CastTest.double
+[ OK ] CastTest.double (0 ms)
+[----------] 1 test from CastTest (0 ms total)
+
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test suite ran. (0 ms total)
+[ PASSED ] 1 test.
+
+INFO: Target tainted ["test"].
+$
+#+END_SRC