-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added CMakeLists.txt
and Makefile
for clean & fast builds of external projects that use Current.
#956
Merged
Merged
Added CMakeLists.txt
and Makefile
for clean & fast builds of external projects that use Current.
#956
Changes from 10 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
b08d33c
Preparing a universal `cmake`-based build.
dimacurrentai 906b632
Added the `Makefile` to accompany this `CMakeLists.txt`.
dimacurrentai 28c875d
Added `cmake/run-cmake-test.sh`.
dimacurrentai baca2bd
Added the `cmake.yml` action.
dimacurrentai 8f1f1ba
Run the `cmake.yml` action on macOS too.
dimacurrentai ea55bfc
Renamed the action.
dimacurrentai cd1bcb2
Made it run on each PR commit.
dimacurrentai d068bac
More Action-friendly output.
dimacurrentai 35d44d5
Added a `TODO`.
dimacurrentai b0a21ec
Added the test for `lib_*.{cc,h}`.
dimacurrentai 92786db
Added support for `.so` targets as well.
dimacurrentai 53ef2ff
Using single quotes instead of tick quotes in `cat <<EOF` because macOS.
dimacurrentai e836870
macOS experiments on Github ...
dimacurrentai c08e357
... more macOS experiments.
dimacurrentai f1e9391
... and even more ...
dimacurrentai 3141d35
Looks like macOS is defeated, tests pass.
dimacurrentai faf8a33
Work in progress for cross-platform `dlopen`.
dimacurrentai 2962d0b
Fixed it!
dimacurrentai d719640
Final `cmake/README.md tweaks.
dimacurrentai 05e56a4
Minor.
dimacurrentai ab8fb2e
Minor II.
dimacurrentai 6e93509
Removed the `q/q/q` test dir, whoa.
dimacurrentai 57208a4
Minor README tweak.
dimacurrentai cdbadb1
Made the test run dir truly nested.
dimacurrentai c52ecc6
The [hopefully] last minor tweak for this PR.
dimacurrentai File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: cmake | ||
|
||
on: | ||
workflow_dispatch: | ||
pull_request: | ||
types: [opened, synchronize] | ||
|
||
jobs: | ||
try-cmake: | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest, macos-latest] | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- name: git clone | ||
uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 1 | ||
- name: run test | ||
run: | | ||
export TESTDIR="cmake_test_$(date +%s)" | ||
echo "Running in ${TESTDIR}" | ||
mkdir "${TESTDIR}" | ||
cp cmake/Makefile "${TESTDIR}/" | ||
cp cmake/CMakeLists.txt "${TESTDIR}/" | ||
cp cmake/run-cmake-test.sh "${TESTDIR}/" | ||
(cd "${TESTDIR}"; ./run-cmake-test.sh) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# TODO(dkorolev): Consider intelligently re-running `cmake` from the `Makefile` if the set of source files has changed. | ||
|
||
cmake_minimum_required(VERSION 3.14.1) | ||
|
||
project(cmake_trivial_2023 C CXX) | ||
|
||
set (CMAKE_CXX_STANDARD 17) | ||
find_package(Threads REQUIRED) | ||
|
||
# Settings for `googletest`. It builds faste without `gmock`. | ||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) | ||
option(BUILD_GMOCK OFF) | ||
|
||
# The helper to clone a dependency, or use it from a sibling dir if available. | ||
function(UseOrGitClone dep remote branch) | ||
if(EXISTS "${CMAKE_SOURCE_DIR}/${dep}" AND IS_DIRECTORY "${CMAKE_SOURCE_DIR}/${dep}") | ||
message(STATUS "Using `${dep}` from `CMAKE_SOURCE_DIR/${dep}'.") | ||
add_subdirectory("${CMAKE_SOURCE_DIR}/${dep}" ${dep}) | ||
message(STATUS "Using `${dep}` from `CMAKE_SOURCE_DIR/${dep}': Configured.") | ||
elseif(EXISTS "${CMAKE_SOURCE_DIR}/../${dep}" AND IS_DIRECTORY "${CMAKE_SOURCE_DIR}/../${dep}") | ||
message(STATUS "Using `${dep}` from `CMAKE_SOURCE_DIR/../${dep}'.") | ||
add_subdirectory("${CMAKE_SOURCE_DIR}/../${dep}" ${dep}) | ||
message(STATUS "Using `${dep}` from `CMAKE_SOURCE_DIR/../${dep}': Configured.") | ||
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../${dep}" AND IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../${dep}") | ||
message(STATUS "Using `${dep}` from `CMAKE_CURRENT_SOURCE_DIR/../${dep}'.") | ||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../${dep}" ${dep}) | ||
message(STATUS "Using `${dep}` from `CMAKE_CURRENT_SOURCE_DIR/../${dep}': Configured.") | ||
else() | ||
message(STATUS "Cloning `${dep}` from `${remote}:${branch}` ...") | ||
execute_process(OUTPUT_QUIET ERROR_QUIET COMMAND git clone --depth 1 -b ${branch} ${remote}) | ||
file(TOUCH .gitignore) | ||
file(APPEND .gitignore "${dep}/\n") | ||
add_subdirectory("${CMAKE_SOURCE_DIR}/${dep}" ${dep}) | ||
message(STATUS "Cloning `${dep}` from `${remote}:${branch}`: Configured.") | ||
endif() | ||
endfunction() | ||
|
||
UseOrGitClone(current https://github.com/c5t/current stable) | ||
UseOrGitClone(googletest https://github.com/c5t/googletest v1.14) | ||
|
||
# Declare libraries as library targets. And add them into the `ALL_LIBRARIES` list. | ||
set(ALL_LIBRARIES "Threads::Threads" "C5T") | ||
file(GLOB_RECURSE LIBRARY_SOURCE_FILES "src/lib_*.cc") | ||
foreach(LIBRARY_SOURCE_FILE ${LIBRARY_SOURCE_FILES}) | ||
get_filename_component(LIBRARY_TARGET_NAME "${LIBRARY_SOURCE_FILE}" NAME_WE) | ||
add_library(${LIBRARY_TARGET_NAME} "${LIBRARY_SOURCE_FILE}") | ||
list(APPEND ALL_LIBRARIES "${LIBRARY_TARGET_NAME}") | ||
endforeach() | ||
|
||
# Declare binaries as binary targets. And link them against all the libraries. | ||
file(GLOB_RECURSE BINARY_SOURCE_FILES "src/*.cc") | ||
foreach(BINARY_SOURCE_FILE ${BINARY_SOURCE_FILES}) | ||
get_filename_component(BINARY_TARGET_NAME "${BINARY_SOURCE_FILE}" NAME_WE) | ||
if(NOT (BINARY_TARGET_NAME MATCHES "^lib_.*$" OR BINARY_TARGET_NAME MATCHES "^test_.*$")) | ||
add_executable(${BINARY_TARGET_NAME} "${BINARY_SOURCE_FILE}") | ||
target_link_libraries(${BINARY_TARGET_NAME} PRIVATE "${ALL_LIBRARIES}") | ||
endif() | ||
endforeach() | ||
|
||
# Declare tests as test targets. And link them against all the libraries. | ||
enable_testing() | ||
file(GLOB_RECURSE TEST_SOURCE_FILES "src/test_*.cc") | ||
foreach(TEST_SOURCE_FILE ${TEST_SOURCE_FILES}) | ||
get_filename_component(TEST_TARGET_NAME "${TEST_SOURCE_FILE}" NAME_WE) | ||
add_executable(${TEST_TARGET_NAME} "${TEST_SOURCE_FILE}") | ||
target_link_libraries(${TEST_TARGET_NAME} PRIVATE gtest_main "${ALL_LIBRARIES}") | ||
add_test(NAME ${TEST_TARGET_NAME} COMMAND ${TEST_TARGET_NAME}) | ||
endforeach() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# NOTE(dkorolev): | ||
# | ||
# Yes, I am well aware it is ugly to have a `Makefile` for a `cmake`-built project. | ||
# | ||
# However, there is quite some value. | ||
# Please see the README of https://github.com/dimacurrentai/Current/tree/cmake/cmake for more details. | ||
# TODO(dkorolev): Fix the repo & branch on the line above once merged. | ||
# | ||
# Besides, this `Makefiles` makes `:mak` in Vim work like a charm! | ||
|
||
.PHONY: release debug release_dir debug_dir release_test debug_test test fmt clean | ||
|
||
DEBUG_BUILD_DIR=$(shell echo "$${DEBUG_BUILD_DIR:-.current_debug}") | ||
RELEASE_BUILD_DIR=$(shell echo "$${RELEASE_BUILD_DIR:-.current}") | ||
|
||
OS=$(shell uname) | ||
ifeq ($(OS),Darwin) | ||
CORES=$(shell sysctl -n hw.physicalcpu) | ||
else | ||
CORES=$(shell nproc) | ||
endif | ||
|
||
CLANG_FORMAT=$(shell echo "$${CLANG_FORMAT:-clang-format}") | ||
|
||
release: release_dir CMakeLists.txt | ||
@MAKEFLAGS=--no-print-directory cmake --build "${RELEASE_BUILD_DIR}" -j ${CORES} | ||
|
||
release_dir: ${RELEASE_BUILD_DIR} | ||
@grep "^${RELEASE_BUILD_DIR}/$$" .gitignore >/dev/null || echo "${RELEASE_BUILD_DIR}/" >>.gitignore | ||
|
||
${RELEASE_BUILD_DIR}: CMakeLists.txt src | ||
@cmake -DCMAKE_BUILD_TYPE=Release -B "${RELEASE_BUILD_DIR}" . | ||
|
||
test: release | ||
@(cd "${RELEASE_BUILD_DIR}"; make test) | ||
|
||
debug: debug_dir CMakeLists.txt | ||
@MAKEFLAGS=--no-print-directory cmake --build "${DEBUG_BUILD_DIR}" -j ${CORES} | ||
|
||
debug_dir: ${DEBUG_BUILD_DIR} | ||
@grep "^${DEBUG_BUILD_DIR}/$$" .gitignore >/dev/null || echo "${DEBUG_BUILD_DIR}/" >>.gitignore | ||
|
||
${DEBUG_BUILD_DIR}: CMakeLists.txt src | ||
@cmake -B "${DEBUG_BUILD_DIR}" . | ||
|
||
debug_test: debug | ||
@(cd "${DEBUG_BUILD_DIR}"; make test) | ||
|
||
test: release_test | ||
|
||
fmt: | ||
${CLANG_FORMAT} -i src/*.cc src/*.h | ||
|
||
# TODO(dkorolev): Use the proper repo & branch name. | ||
CMakeLists.txt: | ||
@curl -s https://raw.githubusercontent.com/dimacurrentai/Current/cmake/cmake/CMakeLists.txt >$@ | ||
# TODO(dkorolev): Fix the repo & branch on the line above once merged. | ||
|
||
clean: | ||
rm -rf "${DEBUG_BUILD_DIR}" "${RELEASE_BUILD_DIR}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# `C5T/current/cmake/` | ||
|
||
This directory contains the `CMakeLists.txt`-based setup for a user project that needs Current. | ||
|
||
This `CMakeLists.txt` is accompanied by a `Makefile`. Together, they: | ||
|
||
* Make the user depend only on the `Makefile`. | ||
* I.e., it is enough to obtain the `Makefile` from this dir, the rest is magic. | ||
* This `Makefile` will `curl` the `CMakeLists.txt` file as needed. | ||
* Builds the code from `src/`. | ||
* Every `src/*.cc` becomes a binary. | ||
* Every `src/lib*.cc` becomes a library. | ||
* Every `src/test*.cc` becomes a test target. | ||
* All libraries are linked to all binaries and tests for this simple setup. | ||
* Defines many useful `make` targets: | ||
* `clean`, `debug`, `release`, `test`, `release_test`, `clean`, `fmt`, etc. | ||
* Uses `current` and `googletest` from `..` or `../..` if they exist. | ||
* Clones `current` and `googletest` if needed. | ||
* Adds them into `.gitignore` if they are cloned into the local dir. | ||
|
||
The `test/` directory in this repo illustrates what it takes to use this `Makefile` + `CMakeLists.txt`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
#!/bin/bash | ||
# | ||
# This script illustrates how to use the CMakeLists.txt-based build of project that use `current`. | ||
# It is meant to be run from within an empty directory. | ||
|
||
set -e | ||
|
||
touch .gitignore | ||
touch golden_gitignore | ||
|
||
if ! diff golden_gitignore .gitignore ; then | ||
echo "Diff failed on line ${LINENO}." | ||
exit 1 | ||
fi | ||
|
||
if ! [ -s Makefile ] ; then | ||
echo 'Need the `Makefile`, `curl`-ing one.' | ||
curl -s https://raw.githubusercontent.com/dimacurrentai/Current/cmake/cmake/Makefile >Makefile | ||
# TODO(dkorolev): Fix the repo & branch on the line above once merged. | ||
fi | ||
|
||
mkdir -p src | ||
cat >src/hw.cc <<EOF | ||
#include <iostream> | ||
int main() { | ||
#ifdef NDEBUG | ||
std::cout << "Hello, World! NDEBUG=1." << std::endl; | ||
#else | ||
std::cout << "Hello, World! NDEBUG is unset." << std::endl; | ||
#endif | ||
} | ||
EOF | ||
|
||
# This runs `cmake .` for Release mode, which is output into `.current`. | ||
echo "::group::configure" | ||
make .current | ||
echo "::endgroup::" | ||
|
||
# The run of `cmake .` must have cloned `current` and `googletest` and added them into `.gitignore`. | ||
if ! [ -d current ] || ! [ -d googletest ] ; then | ||
echo 'Either `current` or `googletest` were not cloned.' | ||
exit 1 | ||
fi | ||
|
||
echo 'current/' >>golden_gitignore | ||
echo 'googletest/' >>golden_gitignore | ||
if ! diff golden_gitignore .gitignore ; then | ||
echo "Diff failed on line ${LINENO}." | ||
exit 1 | ||
fi | ||
|
||
echo "::group::make [release]" | ||
make | ||
echo "::endgroup::" | ||
|
||
echo '.current/' >>golden_gitignore | ||
if ! diff golden_gitignore .gitignore ; then | ||
echo "Diff failed on line ${LINENO}." | ||
exit 1 | ||
fi | ||
|
||
echo "::group::.current/hw" | ||
.current/hw | ||
echo "::endgroup::" | ||
|
||
echo "::group::make debug" | ||
make debug | ||
echo "::endgroup::" | ||
|
||
echo '.current_debug/' >>golden_gitignore | ||
diff golden_gitignore .gitignore || (echo 'Wrong `.gitignore`, exiting.'; exit 1) | ||
|
||
echo "::group::.current_debug/hw" | ||
.current_debug/hw | ||
echo "::endgroup::" | ||
|
||
cat >src/lib_add.cc <<EOF | ||
#include "lib_add.h" | ||
int lib_add(int a, int b) { | ||
return a + b; | ||
} | ||
EOF | ||
|
||
cat >src/lib_add.h <<EOF | ||
#pragma once | ||
int lib_add(int a, int b); | ||
EOF | ||
|
||
cat >src/test_gtest.cc <<EOF | ||
#include <gtest/gtest.h> // IWYU pragma: keep | ||
#include "lib_add.h" | ||
TEST(SmokeGoogletest, TwoTimesTwo) { | ||
EXPECT_EQ(4, 2 * 2); | ||
} | ||
TEST(SmokeGoogletest, TwoPlusThree) { | ||
EXPECT_EQ(5, lib_add(2, 3)); | ||
} | ||
EOF | ||
|
||
cat >src/test_current_gtest.cc <<EOF | ||
#include "3rdparty/gtest/gtest-main.h" // IWYU pragma: keep | ||
#include "lib_add.h" | ||
TEST(SmokeCurrentGoogletest, TwoTimesTwo) { | ||
EXPECT_EQ(4, 2 * 2); | ||
} | ||
TEST(SmokeCurrentGoogletest, TwoPlusThree) { | ||
EXPECT_EQ(5, lib_add(2, 3)); | ||
} | ||
EOF | ||
|
||
echo "::group::release_test" | ||
make test | ||
echo "::endgroup::" | ||
|
||
echo "::group::debug_test" | ||
make debug_test | ||
echo "::endgroup::" | ||
|
||
touch src/test_gtest.cc | ||
T0_GTEST=$(date +%s) | ||
echo "::group::one line change google gtest release" | ||
make test | ||
echo "::endgroup::" | ||
T1_GTEST=$(date +%s) | ||
|
||
touch src/test_current_gtest.cc | ||
T0_CURRENT_GTEST=$(date +%s) | ||
echo "::group::one line change current gtest release" | ||
make test | ||
echo "::endgroup::" | ||
T1_CURRENT_GTEST=$(date +%s) | ||
|
||
touch src/test_gtest.cc | ||
T0_DEBUG_GTEST=$(date +%s) | ||
echo "::group::one line change google gtest debug" | ||
make debug_test | ||
echo "::endgroup::" | ||
T1_DEBUG_GTEST=$(date +%s) | ||
|
||
touch src/test_current_gtest.cc | ||
T0_DEBUG_CURRENT_GTEST=$(date +%s) | ||
echo "::group::one line change current gtest debug" | ||
make debug_test | ||
echo "::endgroup::" | ||
T1_DEBUG_CURRENT_GTEST=$(date +%s) | ||
|
||
echo "One-line change time, Current gtest, debug: $((T1_DEBUG_CURRENT_GTEST - T0_DEBUG_CURRENT_GTEST))s" | ||
echo "One-line change time, Current gtest, release: $((T1_CURRENT_GTEST - T0_CURRENT_GTEST))s" | ||
echo | ||
echo "One-line change time, Google gtest, debug: $((T1_DEBUG_GTEST - T0_DEBUG_GTEST))s" | ||
echo "One-line change time, Google gtest, release: $((T1_GTEST - T0_GTEST))s" | ||
echo | ||
echo '(The numbers for `Current gtest` should be worse, as Current is header-only.)' | ||
|
||
for i in ./.current/test_gtest ./.current/test_current_gtest ./.current_debug/test_gtest ./.current_debug/test_current_gtest ; do | ||
echo "::group::test output for $i" | ||
$i | ||
echo "::endgroup::" | ||
done |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE(dkorolev), @mzhurovich, this was tested a long time ago in https://github.com/dkorolev/example_use_current_with_cmake, just cleaned up a bit and moved this into
current
.'