diff mbox series

[5/5] cmake: avoid editing t/test-lib.sh

Message ID c7fc5a4ee4cbc49b8afb2f9579763482552fffb0.1660143750.git.gitgitgadget@gmail.com (mailing list archive)
State Superseded
Headers show
Series Some fixes and an improvement for using CTest on Windows | expand

Commit Message

Johannes Schindelin Aug. 10, 2022, 3:02 p.m. UTC
From: Johannes Schindelin <johannes.schindelin@gmx.de>

In 7f5397a07c6c (cmake: support for testing git when building out of the
source tree, 2020-06-26), we implemented support for running Git's test
scripts even after building Git in a different directory than the source
directory.

The way we did this was to edit the file `t/test-lib.sh` to override
`GIT_BUILD_DIR` to point somewhere else than the parent of the `t/`
directory.

This is unideal because it always leaves a tracked file marked as
modified, and it is all too easy to commit that change by mistake.

Let's change the strategy by teaching `t/test-lib.sh` to detect the
presence of a file called `GIT-BUILD-DIR` in the source directory. If it
exists, the contents are interpreted as the location to the _actual_
build directory. We then write this file as part of the CTest
definition.

To support building Git via a regular `make` invocation after building
it using CMake, we ensure that the `GIT-BUILD-DIR` file is deleted (for
convenience, this is done as part of the Makefile rule that is already
run with every `make` invocation to ensure that `GIT-BUILD-OPTIONS` is
up to date).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 .gitignore                          |  1 +
 Makefile                            |  1 +
 contrib/buildsystems/CMakeLists.txt |  7 +------
 t/test-lib.sh                       | 11 ++++++++++-
 4 files changed, 13 insertions(+), 7 deletions(-)

Comments

Ævar Arnfjörð Bjarmason Aug. 11, 2022, 11:35 a.m. UTC | #1
On Wed, Aug 10 2022, Johannes Schindelin via GitGitGadget wrote:

> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> In 7f5397a07c6c (cmake: support for testing git when building out of the
> source tree, 2020-06-26), we implemented support for running Git's test
> scripts even after building Git in a different directory than the source
> directory.
>
> The way we did this was to edit the file `t/test-lib.sh` to override
> `GIT_BUILD_DIR` to point somewhere else than the parent of the `t/`
> directory.
>
> This is unideal because it always leaves a tracked file marked as
> modified, and it is all too easy to commit that change by mistake.
>
> Let's change the strategy by teaching `t/test-lib.sh` to detect the
> presence of a file called `GIT-BUILD-DIR` in the source directory. If it
> exists, the contents are interpreted as the location to the _actual_
> build directory. We then write this file as part of the CTest
> definition.
>
> To support building Git via a regular `make` invocation after building
> it using CMake, we ensure that the `GIT-BUILD-DIR` file is deleted (for
> convenience, this is done as part of the Makefile rule that is already
> run with every `make` invocation to ensure that `GIT-BUILD-OPTIONS` is
> up to date).
>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>  .gitignore                          |  1 +
>  Makefile                            |  1 +
>  contrib/buildsystems/CMakeLists.txt |  7 +------
>  t/test-lib.sh                       | 11 ++++++++++-
>  4 files changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/.gitignore b/.gitignore
> index a4522157641..b72ddf09346 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -2,6 +2,7 @@
>  /fuzz_corpora
>  /fuzz-pack-headers
>  /fuzz-pack-idx
> +/GIT-BUILD-DIR
>  /GIT-BUILD-OPTIONS
>  /GIT-CFLAGS
>  /GIT-LDFLAGS
> diff --git a/Makefile b/Makefile
> index 04d0fd1fe60..9347ed90da7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -3028,6 +3028,7 @@ else
>  	@echo RUNTIME_PREFIX=\'false\' >>$@+
>  endif
>  	@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
> +	@if test -f GIT-BUILD-DIR; then rm GIT-BUILD-DIR; fi
>  
>  ### Detect Python interpreter path changes
>  ifndef NO_PYTHON
> diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
> index fe606c179f7..29d7e236ae1 100644
> --- a/contrib/buildsystems/CMakeLists.txt
> +++ b/contrib/buildsystems/CMakeLists.txt
> @@ -1067,14 +1067,9 @@ endif()
>  #Make the tests work when building out of the source tree
>  get_filename_component(CACHE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../CMakeCache.txt ABSOLUTE)
>  if(NOT ${CMAKE_BINARY_DIR}/CMakeCache.txt STREQUAL ${CACHE_PATH})
> -	file(RELATIVE_PATH BUILD_DIR_RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/CMakeCache.txt)
> -	string(REPLACE "/CMakeCache.txt" "" BUILD_DIR_RELATIVE ${BUILD_DIR_RELATIVE})
>  	#Setting the build directory in test-lib.sh before running tests
>  	file(WRITE ${CMAKE_BINARY_DIR}/CTestCustom.cmake
> -		"file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh GIT_BUILD_DIR_REPL REGEX \"GIT_BUILD_DIR=(.*)\")\n"
> -		"file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh content NEWLINE_CONSUME)\n"
> -		"string(REPLACE \"\${GIT_BUILD_DIR_REPL}\" \"GIT_BUILD_DIR=\\\"$TEST_DIRECTORY/../${BUILD_DIR_RELATIVE}\\\"\" content \"\${content}\")\n"
> -		"file(WRITE ${CMAKE_SOURCE_DIR}/t/test-lib.sh \${content})")
> +		"file(WRITE ${CMAKE_SOURCE_DIR}/GIT-BUILD-DIR \"${CMAKE_BINARY_DIR}\")")
>  	#misc copies
>  	file(COPY ${CMAKE_SOURCE_DIR}/t/chainlint.sed DESTINATION ${CMAKE_BINARY_DIR}/t/)
>  	file(COPY ${CMAKE_SOURCE_DIR}/po/is.po DESTINATION ${CMAKE_BINARY_DIR}/po/)
> diff --git a/t/test-lib.sh b/t/test-lib.sh
> index 55857af601b..4468ac51f25 100644
> --- a/t/test-lib.sh
> +++ b/t/test-lib.sh
> @@ -42,7 +42,16 @@ then
>  	TEST_OUTPUT_DIRECTORY=$TEST_DIRECTORY
>  fi
>  GIT_BUILD_DIR="${TEST_DIRECTORY%/t}"
> -if test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
> +if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR"
> +then
> +	GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1
> +	# On Windows, we must convert Windows paths lest they contain a colon
> +	case "$(uname -s)" in
> +	*MINGW*)
> +		GIT_BUILD_DIR="$(cygpath -au "$GIT_BUILD_DIR")"
> +		;;
> +	esac
> +elif test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
>  then
>  	echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2
>  	exit 1

So we'll now skip the assertion added in 9dbf20e7f62 (test-lib: correct
and assert TEST_DIRECTORY overriding, 2022-02-27), shouldn't these tests
run inside a "t" directory generated in contrib/buildsystems/ ?

This really seems like a hack-upon-hack, and will break some workflows
when you switch back & forth, e.g.:

	make
	# run cmake
	make -C t

Will now pick up this new file, and result in broken tests, as we'll
rely on the now-stale file.

IOW you're making the assumption that by piggy-backing on the
GIT-BUILD-OPTIONS rule that anything that needs it will also *re-run
it*, but that's not the case.

I can think of ways to get around it, but it would be nasty as we'd need
to complete the dependency graph between the two, and figure out the
various interactions.

But why do we need this at all? Right now I tried:

 * (Manually) removing the existing hack
 * Copying t/*lib*.sh over to contrib/buildsystems/t
 * cd contrib/buildsystems/t
 * ../../../t/t0001-init.sh 

Which (aside from a small fixable nit about oid-info) Just Works,
because the cmake build is already creating a GIT-BUILD-OPTIONS.

Presumably that "copying" step should be simlynking, or we'd be smarter
about doing includes from test-lib.sh.

But isn't that a much better approach? Rather than working around the
directory discovery just teach it to run from the generated t/ directory
directly?
Phillip Wood Aug. 11, 2022, 12:58 p.m. UTC | #2
Hi Dscho

On 10/08/2022 16:02, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> In 7f5397a07c6c (cmake: support for testing git when building out of the
> source tree, 2020-06-26), we implemented support for running Git's test
> scripts even after building Git in a different directory than the source
> directory.
> 
> The way we did this was to edit the file `t/test-lib.sh` to override
> `GIT_BUILD_DIR` to point somewhere else than the parent of the `t/`
> directory.
> 
> This is unideal because it always leaves a tracked file marked as
> modified, and it is all too easy to commit that change by mistake.
> 
> Let's change the strategy by teaching `t/test-lib.sh` to detect the
> presence of a file called `GIT-BUILD-DIR` in the source directory. If it
> exists, the contents are interpreted as the location to the _actual_
> build directory. We then write this file as part of the CTest
> definition.

I think it is really good to get away from editing the test files, but 
one of the nice things about CMake's out of tree builds is that you can 
have several build directories with different build configurations and 
this change does not support that. Could we pass the build directory to 
the test scripts as a commandline option or environment variable 
instead? e.g.

   foreach(tsh ${test_scipts})
    	add_test(NAME ${tsh}
-		COMMAND ${SH_EXE} ${tsh} --no-bin-wrappers --no-chain-lint -vx
+		COMMAND ${SH_EXE} ${tsh} --no-bin-wrappers --no-chain-lint 
--build-dir=${CMAKE_BINARY_DIR} -vx

   		WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/t)
   endforeach()

Doing that would avoid changing the main Makefile to remove a file which 
almost certainly does not exist every time make is invoked as well.

Best Wishes

Phillip

> To support building Git via a regular `make` invocation after building
> it using CMake, we ensure that the `GIT-BUILD-DIR` file is deleted (for
> convenience, this is done as part of the Makefile rule that is already
> run with every `make` invocation to ensure that `GIT-BUILD-OPTIONS` is
> up to date).
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>   .gitignore                          |  1 +
>   Makefile                            |  1 +
>   contrib/buildsystems/CMakeLists.txt |  7 +------
>   t/test-lib.sh                       | 11 ++++++++++-
>   4 files changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/.gitignore b/.gitignore
> index a4522157641..b72ddf09346 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -2,6 +2,7 @@
>   /fuzz_corpora
>   /fuzz-pack-headers
>   /fuzz-pack-idx
> +/GIT-BUILD-DIR
>   /GIT-BUILD-OPTIONS
>   /GIT-CFLAGS
>   /GIT-LDFLAGS
> diff --git a/Makefile b/Makefile
> index 04d0fd1fe60..9347ed90da7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -3028,6 +3028,7 @@ else
>   	@echo RUNTIME_PREFIX=\'false\' >>$@+
>   endif
>   	@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
> +	@if test -f GIT-BUILD-DIR; then rm GIT-BUILD-DIR; fi
>   
>   ### Detect Python interpreter path changes
>   ifndef NO_PYTHON
> diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
> index fe606c179f7..29d7e236ae1 100644
> --- a/contrib/buildsystems/CMakeLists.txt
> +++ b/contrib/buildsystems/CMakeLists.txt
> @@ -1067,14 +1067,9 @@ endif()
>   #Make the tests work when building out of the source tree
>   get_filename_component(CACHE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../CMakeCache.txt ABSOLUTE)
>   if(NOT ${CMAKE_BINARY_DIR}/CMakeCache.txt STREQUAL ${CACHE_PATH})
> -	file(RELATIVE_PATH BUILD_DIR_RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/CMakeCache.txt)
> -	string(REPLACE "/CMakeCache.txt" "" BUILD_DIR_RELATIVE ${BUILD_DIR_RELATIVE})
>   	#Setting the build directory in test-lib.sh before running tests
>   	file(WRITE ${CMAKE_BINARY_DIR}/CTestCustom.cmake
> -		"file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh GIT_BUILD_DIR_REPL REGEX \"GIT_BUILD_DIR=(.*)\")\n"
> -		"file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh content NEWLINE_CONSUME)\n"
> -		"string(REPLACE \"\${GIT_BUILD_DIR_REPL}\" \"GIT_BUILD_DIR=\\\"$TEST_DIRECTORY/../${BUILD_DIR_RELATIVE}\\\"\" content \"\${content}\")\n"
> -		"file(WRITE ${CMAKE_SOURCE_DIR}/t/test-lib.sh \${content})")
> +		"file(WRITE ${CMAKE_SOURCE_DIR}/GIT-BUILD-DIR \"${CMAKE_BINARY_DIR}\")")
>   	#misc copies
>   	file(COPY ${CMAKE_SOURCE_DIR}/t/chainlint.sed DESTINATION ${CMAKE_BINARY_DIR}/t/)
>   	file(COPY ${CMAKE_SOURCE_DIR}/po/is.po DESTINATION ${CMAKE_BINARY_DIR}/po/)
> diff --git a/t/test-lib.sh b/t/test-lib.sh
> index 55857af601b..4468ac51f25 100644
> --- a/t/test-lib.sh
> +++ b/t/test-lib.sh
> @@ -42,7 +42,16 @@ then
>   	TEST_OUTPUT_DIRECTORY=$TEST_DIRECTORY
>   fi
>   GIT_BUILD_DIR="${TEST_DIRECTORY%/t}"
> -if test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
> +if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR"
> +then
> +	GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1
> +	# On Windows, we must convert Windows paths lest they contain a colon
> +	case "$(uname -s)" in
> +	*MINGW*)
> +		GIT_BUILD_DIR="$(cygpath -au "$GIT_BUILD_DIR")"
> +		;;
> +	esac
> +elif test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
>   then
>   	echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2
>   	exit 1
Johannes Schindelin Aug. 16, 2022, 10:09 a.m. UTC | #3
Hi Phillip,

On Thu, 11 Aug 2022, Phillip Wood wrote:

> On 10/08/2022 16:02, Johannes Schindelin via GitGitGadget wrote:
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > In 7f5397a07c6c (cmake: support for testing git when building out of the
> > source tree, 2020-06-26), we implemented support for running Git's test
> > scripts even after building Git in a different directory than the source
> > directory.
> >
> > The way we did this was to edit the file `t/test-lib.sh` to override
> > `GIT_BUILD_DIR` to point somewhere else than the parent of the `t/`
> > directory.
> >
> > This is unideal because it always leaves a tracked file marked as
> > modified, and it is all too easy to commit that change by mistake.
> >
> > Let's change the strategy by teaching `t/test-lib.sh` to detect the
> > presence of a file called `GIT-BUILD-DIR` in the source directory. If it
> > exists, the contents are interpreted as the location to the _actual_
> > build directory. We then write this file as part of the CTest
> > definition.
>
> I think it is really good to get away from editing the test files, but one of
> the nice things about CMake's out of tree builds is that you can have several
> build directories with different build configurations and this change does not
> support that. Could we pass the build directory to the test scripts as a
> commandline option or environment variable instead? e.g.
>
>   foreach(tsh ${test_scipts})
>    	add_test(NAME ${tsh}
> -		COMMAND ${SH_EXE} ${tsh} --no-bin-wrappers --no-chain-lint -vx
> +		COMMAND ${SH_EXE} ${tsh} --no-bin-wrappers --no-chain-lint
> --build-dir=${CMAKE_BINARY_DIR} -vx
>
>   		WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/t)
>   endforeach()
>
> Doing that would avoid changing the main Makefile to remove a file which
> almost certainly does not exist every time make is invoked as well.

This is indeed tempting, but one of the things I recommend to Visual
Studio users for ages already is to run the tests in a Git Bash, i.e.
outside of Visual Studio, to allow for passing `--run=...` options and the
likes. This recommendation predates support for CTest, naturally, but it
is still valid.

And that recommended way of running tests would be broken by the suggested
change because the tests would no longer run except when using CTest.

Besides, while the semantics look tempting, the implementation details do
not. The reason is that we use `GIT_BUILD_DIR` to source the
`GIT-BUILD-OPTIONS` and to validate that Git was built, long before we
parse the command-line in `t/test-lib.sh`. I want to refrain from the
prerequisite extensive refactoring required to support this, at least in
the context of this here patch series.

Can we maybe agree that the proposed patch is a net improvement over the
status quo, and think about a better solution independently (without
blocking this here patch)?

Ciao,
Dscho
Phillip Wood Aug. 16, 2022, 2:27 p.m. UTC | #4
Hi Dscho

On 16/08/2022 11:09, Johannes Schindelin wrote:
> Hi Phillip,
> 
> On Thu, 11 Aug 2022, Phillip Wood wrote:
> 
>> On 10/08/2022 16:02, Johannes Schindelin via GitGitGadget wrote:
>>> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>>>
>>> In 7f5397a07c6c (cmake: support for testing git when building out of the
>>> source tree, 2020-06-26), we implemented support for running Git's test
>>> scripts even after building Git in a different directory than the source
>>> directory.
>>>
>>> The way we did this was to edit the file `t/test-lib.sh` to override
>>> `GIT_BUILD_DIR` to point somewhere else than the parent of the `t/`
>>> directory.
>>>
>>> This is unideal because it always leaves a tracked file marked as
>>> modified, and it is all too easy to commit that change by mistake.
>>>
>>> Let's change the strategy by teaching `t/test-lib.sh` to detect the
>>> presence of a file called `GIT-BUILD-DIR` in the source directory. If it
>>> exists, the contents are interpreted as the location to the _actual_
>>> build directory. We then write this file as part of the CTest
>>> definition.
>>
>> I think it is really good to get away from editing the test files, but one of
>> the nice things about CMake's out of tree builds is that you can have several
>> build directories with different build configurations and this change does not
>> support that. Could we pass the build directory to the test scripts as a
>> commandline option or environment variable instead? e.g.
>>
>>    foreach(tsh ${test_scipts})
>>     	add_test(NAME ${tsh}
>> -		COMMAND ${SH_EXE} ${tsh} --no-bin-wrappers --no-chain-lint -vx
>> +		COMMAND ${SH_EXE} ${tsh} --no-bin-wrappers --no-chain-lint
>> --build-dir=${CMAKE_BINARY_DIR} -vx
>>
>>    		WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/t)
>>    endforeach()
>>
>> Doing that would avoid changing the main Makefile to remove a file which
>> almost certainly does not exist every time make is invoked as well.
> 
> This is indeed tempting, but one of the things I recommend to Visual
> Studio users for ages already is to run the tests in a Git Bash, i.e.
> outside of Visual Studio, to allow for passing `--run=...` options and the
> likes. This recommendation predates support for CTest, naturally, but it
> is still valid.
> 
> And that recommended way of running tests would be broken by the suggested
> change because the tests would no longer run except when using CTest.

Yes the recommendation would have to include adding --build-dir which 
would be a pain

> Besides, while the semantics look tempting, the implementation details do
> not. The reason is that we use `GIT_BUILD_DIR` to source the
> `GIT-BUILD-OPTIONS` and to validate that Git was built, long before we
> parse the command-line in `t/test-lib.sh`. I want to refrain from the
> prerequisite extensive refactoring required to support this, at least in
> the context of this here patch series.

That sounds awkward.

> Can we maybe agree that the proposed patch is a net improvement over the
> status quo, and think about a better solution independently (without
> blocking this here patch)?

It is definitely an improvement for the CMake side, I'm not sure it is 
an improvement for the Makefile but it sounds like the best option overall.

Best Wishes

Phillip

> Ciao,
> Dscho
Johannes Schindelin Oct. 18, 2022, 2:02 p.m. UTC | #5
Hi Ævar,

On Thu, 11 Aug 2022, Ævar Arnfjörð Bjarmason wrote:

> On Wed, Aug 10 2022, Johannes Schindelin via GitGitGadget wrote:
>
> > From: Johannes Schindelin <johannes.schindelin@gmx.de>
> >
> > In 7f5397a07c6c (cmake: support for testing git when building out of the
> > source tree, 2020-06-26), we implemented support for running Git's test
> > scripts even after building Git in a different directory than the source
> > directory.
> >
> > The way we did this was to edit the file `t/test-lib.sh` to override
> > `GIT_BUILD_DIR` to point somewhere else than the parent of the `t/`
> > directory.
> >
> > This is unideal because it always leaves a tracked file marked as
> > modified, and it is all too easy to commit that change by mistake.
> >
> > Let's change the strategy by teaching `t/test-lib.sh` to detect the
> > presence of a file called `GIT-BUILD-DIR` in the source directory. If it
> > exists, the contents are interpreted as the location to the _actual_
> > build directory. We then write this file as part of the CTest
> > definition.
> >
> > To support building Git via a regular `make` invocation after building
> > it using CMake, we ensure that the `GIT-BUILD-DIR` file is deleted (for
> > convenience, this is done as part of the Makefile rule that is already
> > run with every `make` invocation to ensure that `GIT-BUILD-OPTIONS` is
> > up to date).
> >
> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> > ---
> >  .gitignore                          |  1 +
> >  Makefile                            |  1 +
> >  contrib/buildsystems/CMakeLists.txt |  7 +------
> >  t/test-lib.sh                       | 11 ++++++++++-
> >  4 files changed, 13 insertions(+), 7 deletions(-)
> >
> > diff --git a/.gitignore b/.gitignore
> > index a4522157641..b72ddf09346 100644
> > --- a/.gitignore
> > +++ b/.gitignore
> > @@ -2,6 +2,7 @@
> >  /fuzz_corpora
> >  /fuzz-pack-headers
> >  /fuzz-pack-idx
> > +/GIT-BUILD-DIR
> >  /GIT-BUILD-OPTIONS
> >  /GIT-CFLAGS
> >  /GIT-LDFLAGS
> > diff --git a/Makefile b/Makefile
> > index 04d0fd1fe60..9347ed90da7 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -3028,6 +3028,7 @@ else
> >  	@echo RUNTIME_PREFIX=\'false\' >>$@+
> >  endif
> >  	@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
> > +	@if test -f GIT-BUILD-DIR; then rm GIT-BUILD-DIR; fi
> >
> >  ### Detect Python interpreter path changes
> >  ifndef NO_PYTHON
> > diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
> > index fe606c179f7..29d7e236ae1 100644
> > --- a/contrib/buildsystems/CMakeLists.txt
> > +++ b/contrib/buildsystems/CMakeLists.txt
> > @@ -1067,14 +1067,9 @@ endif()
> >  #Make the tests work when building out of the source tree
> >  get_filename_component(CACHE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../CMakeCache.txt ABSOLUTE)
> >  if(NOT ${CMAKE_BINARY_DIR}/CMakeCache.txt STREQUAL ${CACHE_PATH})
> > -	file(RELATIVE_PATH BUILD_DIR_RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/CMakeCache.txt)
> > -	string(REPLACE "/CMakeCache.txt" "" BUILD_DIR_RELATIVE ${BUILD_DIR_RELATIVE})
> >  	#Setting the build directory in test-lib.sh before running tests
> >  	file(WRITE ${CMAKE_BINARY_DIR}/CTestCustom.cmake
> > -		"file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh GIT_BUILD_DIR_REPL REGEX \"GIT_BUILD_DIR=(.*)\")\n"
> > -		"file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh content NEWLINE_CONSUME)\n"
> > -		"string(REPLACE \"\${GIT_BUILD_DIR_REPL}\" \"GIT_BUILD_DIR=\\\"$TEST_DIRECTORY/../${BUILD_DIR_RELATIVE}\\\"\" content \"\${content}\")\n"
> > -		"file(WRITE ${CMAKE_SOURCE_DIR}/t/test-lib.sh \${content})")
> > +		"file(WRITE ${CMAKE_SOURCE_DIR}/GIT-BUILD-DIR \"${CMAKE_BINARY_DIR}\")")
> >  	#misc copies
> >  	file(COPY ${CMAKE_SOURCE_DIR}/t/chainlint.sed DESTINATION ${CMAKE_BINARY_DIR}/t/)
> >  	file(COPY ${CMAKE_SOURCE_DIR}/po/is.po DESTINATION ${CMAKE_BINARY_DIR}/po/)
> > diff --git a/t/test-lib.sh b/t/test-lib.sh
> > index 55857af601b..4468ac51f25 100644
> > --- a/t/test-lib.sh
> > +++ b/t/test-lib.sh
> > @@ -42,7 +42,16 @@ then
> >  	TEST_OUTPUT_DIRECTORY=$TEST_DIRECTORY
> >  fi
> >  GIT_BUILD_DIR="${TEST_DIRECTORY%/t}"
> > -if test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
> > +if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR"
> > +then
> > +	GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1
> > +	# On Windows, we must convert Windows paths lest they contain a colon
> > +	case "$(uname -s)" in
> > +	*MINGW*)
> > +		GIT_BUILD_DIR="$(cygpath -au "$GIT_BUILD_DIR")"
> > +		;;
> > +	esac
> > +elif test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
> >  then
> >  	echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2
> >  	exit 1
>
> So we'll now skip the assertion added in 9dbf20e7f62 (test-lib: correct
> and assert TEST_DIRECTORY overriding, 2022-02-27), shouldn't these tests
> run inside a "t" directory generated in contrib/buildsystems/ ?
>
> This really seems like a hack-upon-hack, and will break some workflows
> when you switch back & forth, e.g.:
>
> 	make
> 	# run cmake
> 	make -C t
>
> Will now pick up this new file, and result in broken tests, as we'll
> rely on the now-stale file.
>
> IOW you're making the assumption that by piggy-backing on the
> GIT-BUILD-OPTIONS rule that anything that needs it will also *re-run
> it*, but that's not the case.
>
> I can think of ways to get around it, but it would be nasty as we'd need
> to complete the dependency graph between the two, and figure out the
> various interactions.
>
> But why do we need this at all? Right now I tried:
>
>  * (Manually) removing the existing hack
>  * Copying t/*lib*.sh over to contrib/buildsystems/t
>  * cd contrib/buildsystems/t
>  * ../../../t/t0001-init.sh

I appreciate that you want to make it easier for developers. From my
experience with (Windows) developers, I have to point out that what you
describe is _not_ easier than `cd t && ./t0001-init.sh`, though.

It might be easier from some point of view that seems vaguely familiar,
but the user experience of this approach looks prohibitively bad to me.

> Which (aside from a small fixable nit about oid-info) Just Works,
> because the cmake build is already creating a GIT-BUILD-OPTIONS.
>
> Presumably that "copying" step should be simlynking, or we'd be smarter
> about doing includes from test-lib.sh.
>
> But isn't that a much better approach? Rather than working around the
> directory discovery just teach it to run from the generated t/ directory
> directly?

I am sure I could poke more holes into that approach, probably whipping
out something something about `contrib/`, but the user experience alone
(so, dear developer, contrary to what you read in the README and in other
documentation flying all over the internet, yes, you need to switch to
`contrib/buildsystems`, no wait, there's a typo, there's no dash between
`build` and `systems`, there you go, why `buildsystems`? Well, it's just
the way it is. Yes. Now, type out, no, no, wait, *wait!*, you cannot run
`t0006-date.sh` directly as documented, no, wait, you need to prefix it
with this here, and now carefully count the dots, yep, that's right, six
dots in total, three slashes, then a `t/`, yes, I know you were already in
`t/` but not _that_ `t/`, there are now two of 'em, yes, it is
unintuitive, you're absolutely correct, but you know...) is enough for me
to not want to consider this approach any further.

Ciao,
Johannes
diff mbox series

Patch

diff --git a/.gitignore b/.gitignore
index a4522157641..b72ddf09346 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@ 
 /fuzz_corpora
 /fuzz-pack-headers
 /fuzz-pack-idx
+/GIT-BUILD-DIR
 /GIT-BUILD-OPTIONS
 /GIT-CFLAGS
 /GIT-LDFLAGS
diff --git a/Makefile b/Makefile
index 04d0fd1fe60..9347ed90da7 100644
--- a/Makefile
+++ b/Makefile
@@ -3028,6 +3028,7 @@  else
 	@echo RUNTIME_PREFIX=\'false\' >>$@+
 endif
 	@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
+	@if test -f GIT-BUILD-DIR; then rm GIT-BUILD-DIR; fi
 
 ### Detect Python interpreter path changes
 ifndef NO_PYTHON
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index fe606c179f7..29d7e236ae1 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -1067,14 +1067,9 @@  endif()
 #Make the tests work when building out of the source tree
 get_filename_component(CACHE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../CMakeCache.txt ABSOLUTE)
 if(NOT ${CMAKE_BINARY_DIR}/CMakeCache.txt STREQUAL ${CACHE_PATH})
-	file(RELATIVE_PATH BUILD_DIR_RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/CMakeCache.txt)
-	string(REPLACE "/CMakeCache.txt" "" BUILD_DIR_RELATIVE ${BUILD_DIR_RELATIVE})
 	#Setting the build directory in test-lib.sh before running tests
 	file(WRITE ${CMAKE_BINARY_DIR}/CTestCustom.cmake
-		"file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh GIT_BUILD_DIR_REPL REGEX \"GIT_BUILD_DIR=(.*)\")\n"
-		"file(STRINGS ${CMAKE_SOURCE_DIR}/t/test-lib.sh content NEWLINE_CONSUME)\n"
-		"string(REPLACE \"\${GIT_BUILD_DIR_REPL}\" \"GIT_BUILD_DIR=\\\"$TEST_DIRECTORY/../${BUILD_DIR_RELATIVE}\\\"\" content \"\${content}\")\n"
-		"file(WRITE ${CMAKE_SOURCE_DIR}/t/test-lib.sh \${content})")
+		"file(WRITE ${CMAKE_SOURCE_DIR}/GIT-BUILD-DIR \"${CMAKE_BINARY_DIR}\")")
 	#misc copies
 	file(COPY ${CMAKE_SOURCE_DIR}/t/chainlint.sed DESTINATION ${CMAKE_BINARY_DIR}/t/)
 	file(COPY ${CMAKE_SOURCE_DIR}/po/is.po DESTINATION ${CMAKE_BINARY_DIR}/po/)
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 55857af601b..4468ac51f25 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -42,7 +42,16 @@  then
 	TEST_OUTPUT_DIRECTORY=$TEST_DIRECTORY
 fi
 GIT_BUILD_DIR="${TEST_DIRECTORY%/t}"
-if test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
+if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR"
+then
+	GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1
+	# On Windows, we must convert Windows paths lest they contain a colon
+	case "$(uname -s)" in
+	*MINGW*)
+		GIT_BUILD_DIR="$(cygpath -au "$GIT_BUILD_DIR")"
+		;;
+	esac
+elif test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR"
 then
 	echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2
 	exit 1