I am trying to generate C/C++ source files via a Python script using CMake, but am running into an issue where it appears that pipenv is not working as expected.
I’ve attempted to create a simplified version of my real world example on my Github.
cmake_minimum_required(VERSION 2.8.5) project(example) include_directories(${PROJECT_SOURCE_DIR}/src) find_package(Python3 COMPONENTS Interpreter REQUIRED) find_program(PipEnv pipenv REQUIRED) # Create command to compile the generate command add_custom_command( OUTPUT ${CMAKE_SOURCE_DIR}/generate.py COMMAND ${PipEnv} install COMMENT "Installing pipenv dependencies [${PipEnv} install]" DEPENDS ${CMAKE_SOURCE_DIR}/generate.py ${CMAKE_SOURCE_DIR}/Pipfile ) add_custom_target( generate_version COMMAND ${PipEnv} run ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/generate.py -o src/version.h config.json COMMENT "Generating version header [${PipEnv} run ${CMAKE_SOURCE_DIR}/generate.py -o src/version.h config.json]" DEPENDS ${CMAKE_SOURCE_DIR}/generate.py ${CMAKE_SOURCE_DIR}/config.json ) add_subdirectory(src)
The error I am receiving is:
[main] Building folder: Python_example [build] Starting build [proc] Executing command: "C:Program FilesCMakebincmake.EXE" --build c:/src/cmake-auto-increment-build-number/Python_example/build --config Debug --target ALL_BUILD -- /maxcpucount:10 [build] CMake is re-running because C:/src/cmake-auto-increment-build-number/Python_example/build/CMakeFiles/generate.stamp is out-of-date. [build] the file 'C:/src/cmake-auto-increment-build-number/Python_example/CMakeLists.txt' [build] is newer than 'C:/src/cmake-auto-increment-build-number/Python_example/build/CMakeFiles/generate.stamp.depend' [build] result='-1' [build] -- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.18363. [build] -- Configuring done [build] -- Generating done [build] -- Build files have been written to: C:/src/cmake-auto-increment-build-number/Python_example/build [build] Microsoft (R) Build Engine version 16.3.2+e481bbf88 for .NET Framework [build] Copyright (C) Microsoft Corporation. All rights reserved. [build] [build] Checking Build System [build] Generating version header [C:/Program Files/Python38/Scripts/pipenv.exe run C:/src/cmake-auto-increment-build-number/Python_example/generate.py -o src/version.h config.json] [build] Traceback (most recent call last): [build] File "C:/src/cmake-auto-increment-build-number/Python_example/generate.py", line 14, in <module> [build] from docopt import docopt [build] ModuleNotFoundError: No module named 'docopt' [build] C:Program Files (x86)Microsoft Visual Studio2019CommunityMSBuildMicrosoftVCv160Microsoft.CppCommon.targets(230,5): error MSB6006: "cmd.exe" exited with code 1. [C:srccmake-auto-increment-build-numberPython_examplebuildgenerate_version.vcxproj] [build] Build finished with exit code 1
I’ve tried changing the COMMAND
arg for add_custom_target()
to ${PipEnv} install
, but that had no effect. Is there something else I need to be passing to pipenv or the CMake command to get this working?
Advertisement
Answer
Couple of errors here…
Your custom command output and depends of the same file, generate.py
note: you can see a make error in the traceBy default add_custom_command will the current source dir as working directy while custom target is run in the current build dir.
i.e. both are running in different directory -> two different pipenv used…You muse use
pipenv run python
instead ofpipenv run ${Python3_EXECUTABLE}
…here my Dockerfile to run some tests
# Create a virtual environment with all tools installed # ref: https://hub.docker.com/_/ubuntu FROM ubuntu:rolling AS base LABEL maintainer="mizux.dev@gmail.com" # Install system build dependencies ENV PATH=/usr/local/bin:$PATH RUN apt-get update -qq && apt-get install -yq git wget build-essential && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Install CMake 3.18.1 RUN wget "https://cmake.org/files/v3.18/cmake-3.18.1-Linux-x86_64.sh" && chmod a+x cmake-3.18.1-Linux-x86_64.sh && ./cmake-3.18.1-Linux-x86_64.sh --prefix=/usr/local/ --skip-license && rm cmake-3.18.1-Linux-x86_64.sh CMD [ "/usr/bin/bash" ] # Install Python 3.8 RUN apt-get update -qq && apt-get install -yq python3-dev python3-pip && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Install pipenv RUN python3 -m pip install pipenv FROM base AS devel WORKDIR /home/sample COPY . . FROM devel AS build RUN cmake -S. -Bbuild RUN cmake --build build --target all -v
To Build:
docker build --target=build --tag so .
To Play (i.e. stop a devel stage then spawn a container to play):
docker build --target=devel --tag so . docker run --rm -it so
So you modified CMakeLists.txt
cmake_minimum_required(VERSION 2.8.5) project(example) include_directories(${PROJECT_SOURCE_DIR}/src) find_package(Python3 COMPONENTS Interpreter REQUIRED) find_program(PipEnv pipenv REQUIRED) # Create command to compile the generate command add_custom_command( OUTPUT Pipfile.lock COMMAND pwd COMMAND ${PipEnv} install COMMENT "Installing pipenv dependencies [${PipEnv} install]" DEPENDS Pipfile WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_custom_target( generate_version COMMAND pwd COMMAND ${PipEnv} run python generate.py -o src/version.h config.json COMMENT "Generating version header [${PipEnv} run ${CMAKE_SOURCE_DIR}/generate.py -o src/version.h config.json]" DEPENDS Pipfile.lock generate.py config.json WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_subdirectory(src)