From db8b35cf223a4953224a89ec91e0d97d9aa88fc7 Mon Sep 17 00:00:00 2001 From: Sergey Katrevich Date: Wed, 27 May 2020 11:19:46 +0300 Subject: [PATCH 1/2] Added fixed cmake example (only building by standard cmake rules) --- examples/cmake-win/CMakeLists.txt | 80 ++++++++++++++++++++++ examples/cmake-win/README.md | 72 +++++++++++++++++++ examples/cmake-win/fix-build.lisp | 60 ++++++++++++++++ examples/cmake-win/generate.bat | 1 + examples/cmake-win/save-arg.bat | 15 ++++ examples/cmake-win/src/lisp/core-lisp.asd | 2 + examples/cmake-win/src/lisp/core-lisp.lisp | 1 + examples/cmake-win/tmp-env-data.txt | 5 ++ 8 files changed, 236 insertions(+) create mode 100644 examples/cmake-win/CMakeLists.txt create mode 100644 examples/cmake-win/README.md create mode 100644 examples/cmake-win/fix-build.lisp create mode 100644 examples/cmake-win/generate.bat create mode 100644 examples/cmake-win/save-arg.bat create mode 100644 examples/cmake-win/src/lisp/core-lisp.asd create mode 100644 examples/cmake-win/src/lisp/core-lisp.lisp create mode 100644 examples/cmake-win/tmp-env-data.txt diff --git a/examples/cmake-win/CMakeLists.txt b/examples/cmake-win/CMakeLists.txt new file mode 100644 index 000000000..b2fbafd3f --- /dev/null +++ b/examples/cmake-win/CMakeLists.txt @@ -0,0 +1,80 @@ +#============================================================================= +# CMake project configuration file. +# Documentation: https://cmake.org/cmake/help/v3.6/ +#============================================================================= +cmake_minimum_required(VERSION 3.6) # released in 2016 +project(cmake_ecl_proj) +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/cmake/Modules/") + +set(ECL_LIBRARY_DIR C:/Programs/ECL) +set(RESULT_CORE_LISP_LIB core-lisp.lib) +######### +set(ECL_INCLUDE_DIR ${ECL_LIBRARY_DIR}) +set(ECL_BIN_PATH ${ECL_LIBRARY_DIR}/ecl.exe) +set(ECL_LIBRARIES ecl.lib) + +set(ENV_DATA_FILE ${CMAKE_CURRENT_SOURCE_DIR}/tmp-env-data.txt) +set(FIX_BUILD_LISP ${CMAKE_CURRENT_SOURCE_DIR}/fix-build.lisp) +set(SAVE_ARG_BAT ${CMAKE_CURRENT_SOURCE_DIR}/save-arg.bat) + +#set(CMAKE_EXE_LINKER_FLAGS ecl) + +include_directories(${ECL_INCLUDE_DIR}) +link_directories(${ECL_LIBRARY_DIR}) + +# Find ECL library. Refer to ./cmake/Modules/FindECL.cmake and +# https://cmake.org/cmake/help/v3.0/command/find_package.html +find_package(ECL REQUIRED) + +# Put lisp sources and other files relevant for compilation here +# Any change of that files will trigger recompilation of `core-lisp` target +set(CORE_LISP_SOURCES + src/lisp/core-lisp.asd + src/lisp/core-lisp.lisp) + +# Specify how `core-lisp` library is build by ECL +# The library is going to be built statically and moved to +# ${CMAKE_CURRENT_BINARY_DIR}. + +# How to customize +# ================ +# You can change "core-lisp" consistently to different name. +# Value of `:init-name` keyword must match extern declaration in C++ code. + +# Remember to end path with / here. Notably ....src/lisp/, not ....src/lisp +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${RESULT_CORE_LISP_LIB} + COMMAND ${SAVE_ARG_BAT} new ${ENV_DATA_FILE} + COMMAND ${SAVE_ARG_BAT} add ${ENV_DATA_FILE} CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND ${SAVE_ARG_BAT} add ${ENV_DATA_FILE} CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${SAVE_ARG_BAT} add ${ENV_DATA_FILE} CMAKE_CUR_DIR_WITH_LISP ${CMAKE_CURRENT_SOURCE_DIR}/src/lisp/ + COMMAND ${SAVE_ARG_BAT} add ${ENV_DATA_FILE} init_lib_CORE_LISP init_lib_CORE_LISP + COMMAND ${ECL_BIN_PATH} --norc --load "${FIX_BUILD_LISP}" + DEPENDS ${CORE_LISP_SOURCES} +) + +# This goes in pair with `add_custom_command` above. +add_custom_target(core-lisp ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${RESULT_CORE_LISP_LIB}) + +#add_custom_target(ecl_lib "ecl.lib") + +# Define executable to build. You can add other sources here. +# You may change "cmake_ecl" consistently into any name. +add_executable(cmake_ecl + src/cxx/main.cpp) + +#add_library(ecl_lib STATIC IMPORTED "ecl.lib") +# Make cmake_ecl depend on core-lisp so it's going to be build before executable +#add_dependencies(cmake_ecl core-lisp ecl_lib) +add_dependencies(cmake_ecl core-lisp) + +# Set what should be linked into `cmake_ecl` executable. +target_link_libraries(cmake_ecl + ${ECL_LIBRARIES} + ${CMAKE_CURRENT_BINARY_DIR}/${RESULT_CORE_LISP_LIB} + ecl) + +set_target_properties(cmake_ecl PROPERTIES + # Set c++ standard + CXX_STANDARD 17 + # Do you want to use custom compiler extensions? + CXX_EXTENSION ON) diff --git a/examples/cmake-win/README.md b/examples/cmake-win/README.md new file mode 100644 index 000000000..75431ad59 --- /dev/null +++ b/examples/cmake-win/README.md @@ -0,0 +1,72 @@ +# Description +This example shows how to setup CMake to build C++ project which uses ECL library. + +In `src/lisp` is definition of `core-lisp` system that's being loaded into C++ +program. + +Functions defined in `src/lisp/core-lisp.lisp`: +``` +(defun hello-world () (format t "Hello World!~%")) +``` +are used in `src/cxx/main.cpp`: +``` +extern "C" { + extern void init_lib_CORE_LISP(cl_object); +} + +int main(int argc, char** argv) { + cl_boot(argc, argv); + ecl_init_module(NULL, init_lib_CORE_LISP); + cl_eval(c_string_to_object("(hello-world)")); + cl_shutdown(); + return 0; +} +``` + +## CMakeLists.txt +For more information about setup read `CMakeLists.txt` comments. + +# Build +Run: +``` +$ mkdir build +$ cd build +``` +If ECL is built and installed with non-default prefix use: + +``` +$ cmake -DCMAKE_PREFIX_PATH=/home/user/local_prefix/ .. +``` + +Otherwise you don't have to set `CMAKE_PREFIX_PATH`: +``` +$ cmake .. +``` + +Finally run: +``` +$ make +``` + +It shall produce: `cmake_ecl` executable and `core-lisp.a` static library that +has been linked to executable. + + +# Run +``` +$ ./cmake_ecl +Hello World! +``` + +# Notes + 1. You don't have to remove `./build` directory if you want to change option + in `CMakeLists.txt`. Just run `make`. + + 2. If you see `undefined reference` errors look at `nm --demangle core-lisp.a` + output. You may have forgot setting `:init-name` in `CMakeLists.txt` + + 3. To reuse this example you must copy `cmake` directory to your project. It + contains `FindECL.cmake` + + 4. You don't have to have `ecl` executable in `$PATH` environment variable. + `FindECL.cmake` shall find it. diff --git a/examples/cmake-win/fix-build.lisp b/examples/cmake-win/fix-build.lisp new file mode 100644 index 000000000..00104c21e --- /dev/null +++ b/examples/cmake-win/fix-build.lisp @@ -0,0 +1,60 @@ +(in-package :cl-user) + +(require 'asdf) +(require 'cmp) +(require 'uiop) + +;(setf *load-pathname* #P"C:/last-files/sources/ecl-20.4.24/examples/cmake/fix-build.lisp") +(defparameter *name-generated* "tmp-env-data.txt") +(defparameter *this-dir* (make-pathname :defaults *load-pathname* :name nil :type nil)) +(defparameter *path-generated* (merge-pathnames *name-generated* *this-dir*)) + +(format t "~%============== Reading cmake environment ===============~%") + +(defparameter *lines* nil) + +(defun split (str) + (uiop/utility:split-string str)) + +(defun clean (list) + (remove-if (lambda (elt) (string= "" elt)) list)) + +(progn + (setf *lines* nil) + (with-open-file (s *path-generated*) + (loop + :with is-first = t + :for line = (read-line s nil) + :while line + :do (if (not is-first) + (push (clean (split line)) *lines*) + (setf is-first nil) + )) + *lines*)) + +(defun get-var (name) + (second (assoc name *lines* :test 'string=))) + +;;Example: +;;(get-var "CMAKE_CURRENT_BINARY_DIR") + +(format t "build-env: ~s" *lines*) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(format t "~%============== Building ===============~%") + +;;Remember to end path with / here. Notably ....src/lisp/, not ....src/lisp ; +(push (get-var "CMAKE_CUR_DIR_WITH_LISP") asdf:*central-registry*) +(print "===================") +(print asdf:*central-registry*) +(print "===================") + +(asdf:load-system :core-lisp) + +(asdf:make-build :core-lisp + :type :static-library + :move-here (get-var "CMAKE_CURRENT_BINARY_DIR") + :init-name (get-var "init_lib_CORE_LISP")) + +(quit) + diff --git a/examples/cmake-win/generate.bat b/examples/cmake-win/generate.bat new file mode 100644 index 000000000..aae2d92fd --- /dev/null +++ b/examples/cmake-win/generate.bat @@ -0,0 +1 @@ +cmake -DECL_LIBRARY=ecl.lib -DECL_INCLUDE_DIR=$1\ecl .. diff --git a/examples/cmake-win/save-arg.bat b/examples/cmake-win/save-arg.bat new file mode 100644 index 000000000..7cc0c69a1 --- /dev/null +++ b/examples/cmake-win/save-arg.bat @@ -0,0 +1,15 @@ +@echo off +set cmd=%1 +set file=%2 +set data=%3 +set data2=%4 + +echo ============================ +echo cmd: %cmd% +echo file: %file% +echo data: %data% +echo data2: %data2% +echo ============================= + +if "%cmd%" == "new" echo "REM Auto generated. Here variables for build program" > "%file%" +if "%cmd%" == "add" echo %data% %data2% >> "%file%" \ No newline at end of file diff --git a/examples/cmake-win/src/lisp/core-lisp.asd b/examples/cmake-win/src/lisp/core-lisp.asd new file mode 100644 index 000000000..9a2888905 --- /dev/null +++ b/examples/cmake-win/src/lisp/core-lisp.asd @@ -0,0 +1,2 @@ +(defsystem "core-lisp" + :components ((:file "core-lisp"))) diff --git a/examples/cmake-win/src/lisp/core-lisp.lisp b/examples/cmake-win/src/lisp/core-lisp.lisp new file mode 100644 index 000000000..931fa9dbe --- /dev/null +++ b/examples/cmake-win/src/lisp/core-lisp.lisp @@ -0,0 +1 @@ +(defun hello-world () (format t "Hello World!~%")) diff --git a/examples/cmake-win/tmp-env-data.txt b/examples/cmake-win/tmp-env-data.txt new file mode 100644 index 000000000..d8244ad94 --- /dev/null +++ b/examples/cmake-win/tmp-env-data.txt @@ -0,0 +1,5 @@ +"REM Auto generated. Here variables for build program" +CMAKE_CURRENT_SOURCE_DIR C:/last-files/sources/ecl-20.4.24/examples/cmake-win +CMAKE_CURRENT_BINARY_DIR C:/last-files/sources/ecl-20.4.24/examples/cmake-win/build +CMAKE_CUR_DIR_WITH_LISP C:/last-files/sources/ecl-20.4.24/examples/cmake-win/src/lisp/ +init_lib_CORE_LISP init_lib_CORE_LISP -- GitLab From c29810b5dc2dc9af3cbf42f347eee30b45d5192d Mon Sep 17 00:00:00 2001 From: Sergey Katrevich Date: Wed, 27 May 2020 21:35:24 +0300 Subject: [PATCH 2/2] Some fixes cmake-win example - rid of hardcoded path - up cleaning env vars transmitted from CMakeLists.txt - fix-build.lisp: groupped code into progn form for simplify debugging --- examples/cmake-win/CMakeLists.txt | 2 +- examples/cmake-win/fix-build.lisp | 13 ++++++++++--- examples/cmake-win/generate.bat | 2 +- examples/cmake-win/tmp-env-data.txt | 6 +----- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/cmake-win/CMakeLists.txt b/examples/cmake-win/CMakeLists.txt index b2fbafd3f..85143e177 100644 --- a/examples/cmake-win/CMakeLists.txt +++ b/examples/cmake-win/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.6) # released in 2016 project(cmake_ecl_proj) set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/cmake/Modules/") -set(ECL_LIBRARY_DIR C:/Programs/ECL) +set(ECL_LIBRARY_DIR ${ECL_DIR}) set(RESULT_CORE_LISP_LIB core-lisp.lib) ######### set(ECL_INCLUDE_DIR ${ECL_LIBRARY_DIR}) diff --git a/examples/cmake-win/fix-build.lisp b/examples/cmake-win/fix-build.lisp index 00104c21e..76c113797 100644 --- a/examples/cmake-win/fix-build.lisp +++ b/examples/cmake-win/fix-build.lisp @@ -4,7 +4,8 @@ (require 'cmp) (require 'uiop) -;(setf *load-pathname* #P"C:/last-files/sources/ecl-20.4.24/examples/cmake/fix-build.lisp") +;(setf *load-pathname* nil) // Change it (but comment) for debugging +(progn (defparameter *name-generated* "tmp-env-data.txt") (defparameter *this-dir* (make-pathname :defaults *load-pathname* :name nil :type nil)) (defparameter *path-generated* (merge-pathnames *name-generated* *this-dir*)) @@ -17,7 +18,12 @@ (uiop/utility:split-string str)) (defun clean (list) - (remove-if (lambda (elt) (string= "" elt)) list)) + (remove-if (lambda (elt) (or + (string= "" elt) + (string= " +" elt) + )) + list)) (progn (setf *lines* nil) @@ -50,11 +56,12 @@ (print "===================") (asdf:load-system :core-lisp) +) + (asdf:make-build :core-lisp :type :static-library :move-here (get-var "CMAKE_CURRENT_BINARY_DIR") :init-name (get-var "init_lib_CORE_LISP")) -(quit) diff --git a/examples/cmake-win/generate.bat b/examples/cmake-win/generate.bat index aae2d92fd..5f4ec726e 100644 --- a/examples/cmake-win/generate.bat +++ b/examples/cmake-win/generate.bat @@ -1 +1 @@ -cmake -DECL_LIBRARY=ecl.lib -DECL_INCLUDE_DIR=$1\ecl .. +cmake -DECL_DIR=%1 -DECL_LIBRARY=ecl.lib -DECL_INCLUDE_DIR=%1\ecl .. diff --git a/examples/cmake-win/tmp-env-data.txt b/examples/cmake-win/tmp-env-data.txt index d8244ad94..8b1378917 100644 --- a/examples/cmake-win/tmp-env-data.txt +++ b/examples/cmake-win/tmp-env-data.txt @@ -1,5 +1 @@ -"REM Auto generated. Here variables for build program" -CMAKE_CURRENT_SOURCE_DIR C:/last-files/sources/ecl-20.4.24/examples/cmake-win -CMAKE_CURRENT_BINARY_DIR C:/last-files/sources/ecl-20.4.24/examples/cmake-win/build -CMAKE_CUR_DIR_WITH_LISP C:/last-files/sources/ecl-20.4.24/examples/cmake-win/src/lisp/ -init_lib_CORE_LISP init_lib_CORE_LISP + -- GitLab